extends NodeState



@export var igorBoss: IgorBoss


enum SprintState {

	PREPARING,  # 准备冲刺
	SPRINTING,  # 冲刺中
	REBOUND  # 撞墙
}


var sprintState: SprintState
# 准备时间
var preparing_time: float
# 冲刺方向
var sprint_direction: Vector2
# 撞墙后反弹的方向
var rebound_direction: Vector2
# 反弹后横向速度
var rebound_velocity: Vector2
# 反弹高度的速度
var rebound_height_speed: float
# 反弹的高度
var rebound_height: float


func _ready():
	await get_tree().process_frame
	igorBoss.collateralDamageEmitter.body_entered.connect(on_wall_hit)


func _on_process(delta : float) -> void:
	if _changing_state:
		return
	match sprintState:
		SprintState.PREPARING:
			process_pre_sprint(delta)
		SprintState.SPRINTING:
			process_sprint(delta)
		SprintState.REBOUND:
			process_rebound(delta)
	process_animation()
	process_sprint_coillder()


func _on_enter() -> void:
	reset_var()

	igorBoss.collateralDamageEmitter.set_deferred("monitoring", false)
	igorBoss.sprintDamageEmitter.set_deferred("monitoring", true)


func _on_exit() -> void:
	igorBoss.collateralDamageEmitter.set_deferred("monitoring", false)
	igorBoss.sprintDamageEmitter.set_deferred("monitoring", false)


func reset_var():
	sprintState = SprintState.PREPARING
	preparing_time = igorBoss.duration_pre_sprint
	sprint_direction = Vector2.ZERO
	rebound_height_speed = 0.0
	rebound_height = 0.0


func process_animation():
	match sprintState:
		SprintState.PREPARING:
			igorBoss.animationPlayer.play(IgorBoss.ANIMATION_PRE_SPRINT)
		SprintState.SPRINTING:
			igorBoss.animationPlayer.play(IgorBoss.ANIMATION_SPRINT)
		SprintState.REBOUND:
			igorBoss.animationPlayer.play(IgorBoss.ANIMATION_FALL)


func process_pre_sprint(delta: float):
	# 到达准备时间后切换状态
	if preparing_time < 0.0:
		set_sprint_direction()
		sprintState = SprintState.SPRINTING
		igorBoss.collateralDamageEmitter.set_deferred("monitoring", true)
		return
	preparing_time -= delta
	igorBoss.look_at_player()


func process_sprint(delta: float):
	igorBoss.velocity = sprint_direction * igorBoss.sprint_speed * delta
	igorBoss.move_and_slide()



func process_rebound(delta: float):
	igorBoss.characterSprite.position = Vector2.UP * rebound_height
	igorBoss.position += rebound_velocity * delta

	rebound_height += rebound_height_speed * delta
	# 高度降为0时进入倒地状态
	if rebound_height < 0.0:
		rebound_height = 0.0
		rebound_velocity = Vector2.ZERO
		transition_state(IgorBoss.STATE_RECOVER)
	else:
		rebound_height_speed -= igorBoss.gravity * delta


func on_wall_hit(body: Node2D):
	if igorBoss.stateMachine.current_node_state_name != IgorBoss.STATE_SPRINT and sprintState != SprintState.SPRINTING:
		return
	var wall = body as AnimatableBody2D
	if wall == null:
		return
	if check_rebound_wall(wall):
		change_to_rebound(wall)


# 切换到撞墙
func change_to_rebound(wall: AnimatableBody2D):
	igorBoss.look_at_node(wall)
	set_rebound_direction(wall)

	rebound_velocity = rebound_direction * igorBoss.sprint_knockback_intensity
	rebound_height_speed = igorBoss.knockdown_intensity
	sprintState = SprintState.REBOUND
	# 撞墙后，关闭冲刺伤害触发
	igorBoss.sprintDamageEmitter.set_deferred("monitoring", false)



func set_sprint_direction():
	var player_x = igorBoss.player.global_position.x
	var igor_x = igorBoss.global_position.x
	if player_x > igor_x:
		sprint_direction = Vector2.RIGHT
	elif player_x < igor_x:
		sprint_direction = Vector2.LEFT
	else:
		sprint_direction = Vector2.RIGHT if igorBoss.character_orientation() > 0 else Vector2.LEFT


func set_rebound_direction(target: Node2D):
	var target_x = target.global_position.x
	var igor_x = igorBoss.global_position.x
	if target_x > igor_x:
		rebound_direction = Vector2.LEFT
	elif target_x < igor_x:
		rebound_direction = Vector2.RIGHT
	else:
		rebound_direction = Vector2.RIGHT if igorBoss.character_orientation() > 0 else Vector2.LEFT


func check_rebound_wall(wall: AnimatableBody2D) -> bool:
	if wall.is_in_group(GlobalConstants.Group.LEFT_WALL):
		if igorBoss.global_position.x <= wall.global_position.x:
			return false;
	elif wall.is_in_group(GlobalConstants.Group.RIGHT_WALL):
		if igorBoss.global_position.x >= wall.global_position.x:
			return false;
	return true;


func process_sprint_coillder():
	var orientation = igorBoss.character_orientation()
	if orientation == 1:
		igorBoss.sprintDamageEmitter.scale.x = 1
	elif orientation == -1:
		igorBoss.sprintDamageEmitter.scale.x = -1
